package com.jxzn.locust.dto;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.jxzn.locust.support.ResponseCode;

public class ResultDTO<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    int code;
    @JsonInclude(Include.NON_EMPTY)
    String message;
    @JsonInclude(Include.NON_NULL)
    T data;

    public ResultDTO() {
        super();
    }

    @SuppressWarnings({ "rawtypes" })
    public static ResultDTO success() {
        return new ResultDTO(ResponseCode.SUCCESS);
    }

    public static <T> ResultDTO<T> success(T t) {
        return new ResultDTO<T>(t);
    }

    @SuppressWarnings({ "rawtypes" })
    public static ResultDTO error() {
        return new ResultDTO(ResponseCode.ERROR);
    }

    @SuppressWarnings({ "rawtypes" })
    public static ResultDTO param(String message) {
        return new ResultDTO(ResponseCode.PARAM, message);
    }

    @SuppressWarnings({ "rawtypes" })
    public static ResultDTO businessError(String message) {
        return new ResultDTO(ResponseCode.BUSINESS_ERROR, message);
    }

    @SuppressWarnings({ "rawtypes" })
    public static ResultDTO permission(String message) {
        return new ResultDTO(ResponseCode.PERMISSION, message);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static <R> ResultDTO validator(Set<ConstraintViolation<R>> errors) {
        Map<String, String> errorMap = new HashMap<>();
        for (ConstraintViolation<R> error : errors) {
            errorMap.put(error.getPropertyPath().toString(), error.getMessage());
        }
        return new ResultDTO(ResponseCode.PARAM, "", errorMap);
    }

    public ResultDTO(int code, String message, T data) {
        super();
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public ResultDTO(ResponseCode responseCode) {
        this(responseCode, responseCode.getMessage());
    }

    public ResultDTO(ResponseCode responseCode, String message) {
        this(responseCode, message, null);
    }

    public ResultDTO(ResponseCode responseCode, String message, T data) {
        super();
        this.code = responseCode.getCode();
        if (StringUtils.isNotBlank(message)) {
            this.message = message;
        } else {
            this.message = responseCode.getMessage();
        }
        if (null != data) {
            this.data = data;
        }
    }

    public ResultDTO(T data) {
        super();
        this.code = ResponseCode.SUCCESS.getCode();
        this.data = data;
    }

    @JsonIgnore
    public boolean isSuccess() {
        return ResponseCode.SUCCESS.getCode() == this.code;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

}
